package com.alibaba.algo.apiimpl.app;

import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.usercomponent.service.app.AppInfoService;
import com.alibaba.algo.cooperation.usercomponent.vo.req.app.CreateAppRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.app.SelectAppListRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.app.UpdateAppRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.req.app.UpdateAppStateRequestVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.app.FuncInfoResVO;
import com.alibaba.algo.cooperation.usercomponent.vo.res.app.SelectAppListResponseVO;
import com.alibaba.algo.core.base.PagerEntity;
import com.alibaba.algo.core.base.YesOrNo;
import com.alibaba.algo.core.exception.BaseException;
import com.alibaba.algo.domain.app.AppAccountDomain;
import com.alibaba.algo.domain.app.AppFunctionDomain;
import com.alibaba.algo.domain.app.AppInfoDomain;
import com.alibaba.algo.domain.app.FunctionInfoDomain;
import com.alibaba.algo.entity.app.AppAccount;
import com.alibaba.algo.entity.app.AppFunction;
import com.alibaba.algo.entity.app.AppInfo;
import com.alibaba.algo.entity.app.FunctionInfo;
import com.alibaba.algo.enums.AppInfoStateEnum;
import com.alibaba.algo.exception.AppInfoErrorCode;
import com.alibaba.algo.exception.BaseErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 类AppInfoServiceImpl.java的实现描述：应用 serviceimpl
 *
 * @author nieganggang 2021-03-12 16:08:17
 */
@Slf4j
@RestController
public class AppInfoServiceImpl implements AppInfoService {

    @Autowired
    private AppInfoDomain appInfoDomain;

    @Autowired
    private AppFunctionDomain appFunctionDomain;

    @Autowired
    private FunctionInfoDomain functionInfoDomain;

    @Autowired
    private AppAccountDomain appAccountDomain;

    /**
     * 应用新增
     *
     * @param vo 新增信息
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult<Boolean> insert(CreateAppRequestVO vo) {
        // 校验应用信息
        this.checkAppInfo(vo.getAppName(), vo.getAppCode());
        AppInfo appInfo = new AppInfo();
        BeanUtils.copyProperties(vo, appInfo);
        appInfoDomain.insert(appInfo);
        List<Long> functionIdList = vo.getFunctionIdList();
        // 应用功能
        if (!CollectionUtils.isEmpty(functionIdList)) {
            for (Long functionId : functionIdList) {
                // 新增应用账号
                AppAccount appAccount = appAccountDomain.add();
                // 新增应用功能
                AppFunction appFunction = new AppFunction();
                appFunction.setAppId(appInfo.getId());
                appFunction.setFunctionId(functionId);
                appFunction.setAppAccountId(appAccount.getId());
                appFunctionDomain.insert(appFunction);

            }
        }
        return BaseResult.buildSuccess();
    }

    /**
     * 校验应用信息
     *
     * @param appName 应用名称
     * @param appCode 应用编码
     */
    private void checkAppInfo(String appName, String appCode) {
        if (StringUtils.isNotEmpty(appName)) {
            AppInfo appInfo = new AppInfo();
            appInfo.setAppName(appName);
            Integer count = appInfoDomain.listByPara(appInfo, null).size();
            if (count > 0) {
                throw new BaseException(AppInfoErrorCode.APP_NAME_ALREADY_USED.getCode(), AppInfoErrorCode.APP_NAME_ALREADY_USED.getMessage());
            }
        }
        if (StringUtils.isNotEmpty(appCode)) {
            AppInfo appInfo = new AppInfo();
            appInfo.setAppCode(appCode);
            Integer count = appInfoDomain.listByPara(appInfo, null).size();
            if (count > 0) {
                throw new BaseException(AppInfoErrorCode.APP_CODE_ALREADY_USED.getCode(), AppInfoErrorCode.APP_CODE_ALREADY_USED.getMessage());
            }
        }
    }

    /**
     * 应用信息更新
     *
     * @param vo 入参
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult<Boolean> update(UpdateAppRequestVO vo) {
        if (ObjectUtils.isEmpty(vo.getId())) {
            throw new BaseException(BaseErrorCode.APP_ID_IS_NULL.getCode(), BaseErrorCode.APP_ID_IS_NULL.getMessage());
        }
        AppInfo app = appInfoDomain.getById(vo.getId());
        AppInfo appInfo = new AppInfo();
        BeanUtils.copyProperties(vo, appInfo);
        if (ObjectUtils.isEmpty(app)) {
            throw new BaseException(AppInfoErrorCode.APP_IS_NOT_EXIST.getCode(), AppInfoErrorCode.APP_IS_NOT_EXIST.getMessage());
        }
        if (app.getAppName().equals(vo.getAppName())) {
            vo.setAppName(null);
        }
        if (app.getAppCode().equals(vo.getAppCode())) {
            vo.setAppCode(null);
        }
        // 应用信息校验
        this.checkAppInfo(vo.getAppName(), vo.getAppCode());
        appInfoDomain.updateById(appInfo);
        List<Long> functionIds = vo.getFunctionIdList();
        // 删除之前的功能列表,重新添加
        if (!CollectionUtils.isEmpty(functionIds)) {
            Long appId = vo.getId();
            AppFunction appFunctionCon = new AppFunction();
            appFunctionCon.setAppId(appId);
            List<AppFunction> appFunctionList = appFunctionDomain.listByPara(appFunctionCon, new LinkedHashMap<>());
            for (AppFunction af : appFunctionList) {
                af.setIsDeleted(YesOrNo.Y.name());
                appFunctionDomain.updateById(af);
            }
            for (Long functionId : functionIds) {
                // 新增应用账号
                AppAccount appAccount = appAccountDomain.add();
                AppFunction appFunction = new AppFunction();
                appFunction.setAppId(appId);
                appFunction.setAppAccountId(appAccount.getId());
                appFunction.setFunctionId(functionId);
                appFunctionDomain.insert(appFunction);
            }
        }
        return BaseResult.buildSuccess();
    }

    /**
     * 应用开启
     *
     * @param vo 应用标识
     * @return 开启结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult<Boolean> open(UpdateAppStateRequestVO vo) {
        if (ObjectUtils.isEmpty(vo.getAppId())) {
            throw new BaseException(BaseErrorCode.APP_ID_IS_NULL.getCode(), BaseErrorCode.APP_ID_IS_NULL.getMessage());
        }
        AppInfo appInfo = new AppInfo();
        appInfo.setId(vo.getAppId());
        appInfo.setAppState(AppInfoStateEnum.OPEN.getValue());
        appInfoDomain.updateById(appInfo);
        return BaseResult.buildSuccess();
    }

    /**
     * 应用关闭
     *
     * @param vo 应用标识
     * @return 关闭结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult<Boolean> close(UpdateAppStateRequestVO vo) {
        if (ObjectUtils.isEmpty(vo.getAppId())) {
            throw new BaseException(BaseErrorCode.APP_ID_IS_NULL.getCode(), BaseErrorCode.APP_ID_IS_NULL.getMessage());
        }
        AppInfo appInfo = new AppInfo();
        appInfo.setId(vo.getAppId());
        appInfo.setAppState(AppInfoStateEnum.CLOSE.getValue());
        appInfoDomain.updateById(appInfo);
        return BaseResult.buildSuccess();
    }

    /**
     * 批量删除应用
     *
     * @param vo 应用列表
     * @return 删除结果
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public BaseResult<Boolean> delete(List<Long> vo) {
        for (Long appId : vo) {
            this.singleDelete(appId);
        }
        return BaseResult.buildSuccess();
    }

    /**
     * 删除单个应用
     *
     * @param appId 应用标识
     */
    private void singleDelete(Long appId) {
        AppInfo appInfo = new AppInfo();
        appInfo.setId(appId);
        appInfo.setIsDeleted(YesOrNo.Y.name());
        appInfoDomain.updateById(appInfo);
        // 删除应用关联的应用功能列表
        AppFunction appFunctionCon = new AppFunction();
        appFunctionCon.setAppId(appId);
        List<AppFunction> appFunctionList = appFunctionDomain.listByPara(appFunctionCon, new LinkedHashMap<>());
        for (AppFunction appFunction : appFunctionList) {
            appFunction.setIsDeleted(YesOrNo.Y.name());
            appFunctionDomain.updateById(appFunction);
        }
    }

    /**
     * 分页查询
     *
     * @param vo 入参
     * @return 应用列表分页列表
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true, rollbackFor = Exception.class)
    public BaseResult<com.alibaba.algo.cooperation.common.PagerEntity> selectPage(SelectAppListRequestVO vo) {
        AppInfo appInfoCon = new AppInfo();
        BeanUtils.copyProperties(vo, appInfoCon);
        PagerEntity pagerEntity = appInfoDomain.pageByPara(appInfoCon, vo.getPageIndex(), vo.getPageSize(), vo.getSortMap());
        // 处理功能列表
        List<SelectAppListResponseVO> dataList = (List<SelectAppListResponseVO>) pagerEntity.getDataList();
        for (SelectAppListResponseVO s : dataList) {
            if (StringUtils.isEmpty(s.getFunctionIdStr())) {
                continue;
            }
            List<Long> functionIdList = Stream.of(s.getFunctionIdStr().split(","))
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            FunctionInfo functionInfo = new FunctionInfo();
            functionInfo.setFunctionIdList(functionIdList);
            List<FunctionInfo> functionInfos = functionInfoDomain.listByPara(functionInfo, null);
            List<FuncInfoResVO> functionList = new ArrayList<>();
            functionInfos.forEach(f -> {
                FuncInfoResVO funcInfoResVO = new FuncInfoResVO();
                funcInfoResVO.setFunctionId(f.getId());
                funcInfoResVO.setFunctionName(f.getFunctionName());
                functionList.add(funcInfoResVO);
            });
            s.setFunctionList(functionList);
        }
        com.alibaba.algo.cooperation.common.PagerEntity res = new com.alibaba.algo.cooperation.common.PagerEntity();
        BeanUtils.copyProperties(pagerEntity, res);
        return BaseResult.buildSuccess(res);
    }

}
